package controller.parameterpanels;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JTextField;

import model.IManufacturingMethod;
import model.IManufacturingMethodWithPartProcessesAndTools;
import model.auxillary.ParameterCollection;
import model.auxillary.ParameterList;
import model.auxillary.ParameterList.ParameterType;
import model.soldering.ReflowSoldering;
import view.AlphaTextField;
import view.CenterTabbedPane;
import view.NumericalTextField;
import view.parameterpanels.GeometryPanelWithSets;
import view.parameterpanels.GeometryPanelWithSetsAndTools;
import controller.CtrInformationPanel;

/**
 * The class {@code CtrGeometryPanel} specifies the class
 * {@code CtrInputParameterPanel} to control the behavior of a geometry
 * input parameter panel. 
 * @author Oliver Eckstein & Sebastian Perlwitz
 *
 */
public class CtrGeometryPanel extends CtrInputParameterPanel {
	
	/**
     * To create a new {@code CtrGeometryPanel}.
     * @param manuMethod the manufacturing method connected to the controller.
     * @param infoPanelCtr the information panel controller.
     * @param parameterType the type of parameter whose panel gets created.
     * @param logoPath a path to an optional logo that is shown on the
     * parameter panel.
     */
	public CtrGeometryPanel(IManufacturingMethod manuMethod,
			CtrInformationPanel infoPanelCtr, ParameterType parameterType,
			String logoPath) {
		super(manuMethod, infoPanelCtr, parameterType, logoPath);
	}
	
	/*
	 * #changeIfNewManuMethod: Change only necessary if new manufacturing
	 * method uses geometry panels with multiple sets. If this is the case, add
	 * new manuMethod in "if" to to get geometry panels with sets or add new
	 * manuMethod in "else if" to get geometry panels with sets and tools.
	 */
	@Override
	public void createView(String logoPath) {
		
		// Test the type of manuMethod and choose the appropriate GeometryPanel.
		// Either the {@code GeometryPanelWithSets} is chosen or the
		// {@code GeometryPanelWithSetsAndTools}.
		if (manuMethod instanceof ReflowSoldering) {
			paramPanel = new GeometryPanelWithSets(
					logoPath,
					CenterTabbedPane.parameterTypeToTab(parameterType),
					ParameterList.typeToString(parameterType),
					manuMethod);
			GeometryPanelWithSets geomPanel =
					(GeometryPanelWithSets) paramPanel;
			
			// To add listeners to the buttons "+" and "-".
			geomPanel.getPlusButton().addActionListener(
					addGeometrySetListener());
			geomPanel.getSubtractButton()
				.addActionListener(removeGeometrySetListener());
		} else if (manuMethod instanceof 
				IManufacturingMethodWithPartProcessesAndTools) {
			
			paramPanel = new GeometryPanelWithSetsAndTools(
					logoPath,
					CenterTabbedPane.parameterTypeToTab(parameterType),
					ParameterList.typeToString(parameterType),
					(IManufacturingMethodWithPartProcessesAndTools) manuMethod);
			GeometryPanelWithSetsAndTools geomPanel =
					(GeometryPanelWithSetsAndTools) paramPanel;
			
			// To add listeners to the buttons "+" and "-".
			geomPanel.getPlusButton().addActionListener(
					addGeometrySetListener());
			geomPanel.getSubtractButton()
				.addActionListener(removeGeometrySetListener());
		}
	}
	
	@Override
	public void changeBorderText(AlphaTextField textField, String newText) {
		
		// First test the type of manuMethod and then change the corresponding
		// border text when the user renamed the geometry set.
		if (manuMethod instanceof ReflowSoldering) {
			GeometryPanelWithSets geomPanel =
					(GeometryPanelWithSets) paramPanel;
			int panelIndex = 
					geomPanel.getDescriptionTextFields().indexOf(textField);
			paramPanel.setBorderText(panelIndex, newText);
		} else {
		GeometryPanelWithSetsAndTools geomPanel =
				(GeometryPanelWithSetsAndTools) paramPanel;
		int panelIndex = 
				geomPanel.getDescriptionTextFields().indexOf(textField);
		paramPanel.setBorderText(panelIndex, newText);
		}
	}
	
	@Override
	protected void addTextFieldListeners(List<JTextField> textFields) {
		
		// To add text field listeners to the numerical text fields and
		// the text fields that rename a geometry set/border text.
		List<JTextField> numTextFields =
				new ArrayList<JTextField>();
		List<AlphaTextField> alphaTextFields = 
				new ArrayList<AlphaTextField>();
		
		for(JTextField textField : textFields) {
			if(textField instanceof NumericalTextField) {
				numTextFields.add((NumericalTextField) textField);
			} else if(textField instanceof AlphaTextField) {
				alphaTextFields.add((AlphaTextField) textField);
			}
		}
		
		// Add the listeners to the numerical text fields.
		super.addTextFieldListeners(numTextFields);
		
		String partProcessID;		
		for(AlphaTextField textField : alphaTextFields) {
			partProcessID = textField.getParameterID();			
			textField.addDocumentListener(new ListenerAlphaTextField(
					textField,
					this,
					manuMethod,
					partProcessID));
		}
	}

	@Override
	protected void init() {
		List<ParameterCollection> collections = 
    			manuMethod.getParameters(parameterType);
    	for (ParameterCollection collection : collections) {
    		addParameterPanel(collection);  				
    	}
	}

	@Override
	protected void addParameterPanel(ParameterCollection collection) {
		
		// First test the type of manuMethod and then add the appropriate
		// Geometry Panel.
		if (manuMethod instanceof ReflowSoldering) {
			GeometryPanelWithSets geomPanel =
					(GeometryPanelWithSets) paramPanel;
			addTextFieldListeners(
					geomPanel.addParameterSet(
							createParamInfo(collection),
							manuMethod.getPartProcess(
									collection.getPartProcessID()).getName(),						
							collection.getPartProcessID(),
							manuMethod.getPartProcess(
									collection.getPartProcessID()).
									getTextPartProcDescription()));
		} else {
			GeometryPanelWithSetsAndTools geomPanel =
				(GeometryPanelWithSetsAndTools) paramPanel;	
			addTextFieldListeners(
					geomPanel.addParameterSet(
							createParamInfo(collection),
							manuMethod.getPartProcess(
									collection.getPartProcessID()).getName(),
							collection.getPartProcessID(),
							manuMethod.getPartProcess(
								collection.getPartProcessID()).
								getTextPartProcDescription()));
		}
	}

	@Override
	public void changeBorderText(String newText) {
		// Nothing to do here since the border's text depends on the
		// geometry sets' names and not on the manufacturing method's name. 
	}
	
	/**
	 * To create a listener for the button that adds a new geometry set.
	 * @return The button's listener.
	 */
	private ActionListener addGeometrySetListener() {
		return new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				addParameterPanel(
						manuMethod.addPartProcess()
						.getParameterCollection(
								ParameterType.GEOMETRY_PARAMETER));
				paramPanel.revalidate();
			}
		};
	}
	
	/**
	 * To create a listener for the button that removes a new geometry set.
	 * @return The button's listener.
	 */
	private ActionListener removeGeometrySetListener() {
		return new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				// There must be at least one geometry set.
				if(manuMethod.getPartProCount() > 1) {
					removeParameterPanel();
					manuMethod.removePartProcess();
					paramPanel.revalidate();	
				}								
			}			
		};
	}
	
}
